今天在闲逛博客 的时候偶然发现 crispgm 所写的文章,其中推荐了 fzf 这款模糊搜寻工具,所以立马上手体验了一下。

fzf 是一个通用的命令行模糊搜索工具,用 golang 编写,大家的评价都是目前最快的 fuzzy finder,配合 ag 的使用,依靠模糊的关键词,可以快速定位文件。配合一些脚本,可以完全颠覆以前使用命令行的工作方式。

Installation

git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf  ~/.fzf/install
1

or upgrade

cd ~/.fzf && git pull && ./install
1

Demo

最直接的使用方式就是在终端输入:

fzf
1

或者 fzf 可以接受 stdin,比如使用命令

find *  -type f | fzf
1

此时会进入 fzf 的交互窗口,在交互窗口中可以使用 Ctrl + n 或者 Ctrl + p 来上下移动光标。使用 Enter 选中条目

其他常用:

  • Ctrl-j Ctrl-n 都能往下,不过 Ctrl-j 在我的配置中是切换到下 pane 所以我只用 Ctrl-n
  • Ctrl-k Ctrl-p 都能往上,不过 Ctrl-k 在我的配置中是切换到上 pane 所以我只用 Ctrl-p
  • Ctrl-c 或者 Ctrl-g 或者 Ctrl-q 或者 Esc 用来退出 abort
  • Ctrl-h 退格键 backspace,不过这个键和 tmux vim 有冲突所以一般不用
  • Ctrl-a 光标跳转到开头 Ctrl-e 跳转到行结尾
  • Ctrl-w 向前删以 word
  • Ctrl-u 删除所有输入

其实看到后面就发现很多快捷键其实是和 Bash/Shell 下一致的,其他更多的交互命令,可以参考 man fzf

Configuration

FZF_DEFAULT_COMMAND

fzf 默认查找文件使用的是系统的 find 命令,你可以通过自定义该环境变量来更改使用其他命令比如 ag 或者 fd

# 这行配置开启 ag 查找隐藏文件 及忽略 .git 文件  export FZF_DEFAULT_COMMAND='ag --hidden --ignore .git -l -g ""'  # or  export FZF_DEFAULT_COMMAND="fd --exclude={.git,.idea,.sass-cache,node_modules,build} --type f"
1

FZF_DEFAULT_OPTS

该环境变量定义了 fzf 的参数:

export FZF_DEFAULT_OPTS="--height 40% --layout=reverse --preview '(highlight -O ansi {} || cat {}) 2> /dev/null | head -500'"
1

常见的一些操作

fzf 最最常用的快捷键应该就是 Ctrl + r 和 Ctrl + t 了。Ctrl-r 用来在历史中搜索,Ctrl-t 用来搜索当前文件夹下的内容。

历史记录搜索

在没有使用 fzf 之前都是 Ctrl + r 来快速输入历史命令,用起来倒也没有太大的问题,fzf 使得 Ctrl-r 变得更加好用,按下 Ctrl-r 之后立即就能够显示之前的历史命令,通过模糊搜索能够展示一个列表,从列表中选择即可。

历史命令 Ctrl-r

在终端命令行下按下 Ctrl-r 会列出 history 命令目录,选中 Enter 离开 fzf 后,该条目会拷贝到命令行中。

搜索当前文件夹 Ctrl-t

在命令行中按下 Ctrl-t 会打开 fzf 窗口,此时如果找到某文件,并选择 Enter,那么该文件名会被拷贝到命令行中。比如说想要打开某文件但是忘记了名字,那么可以先输入 vi 然后按下 Ctrl-t 那么会出现 fzf 的搜索窗口,在窗口中可以模糊搜索文件,然后将文件路径及文件拷贝到命令行中。

同样的方式,如果要 mv 一个文件,同样先输入 mv 然后再 Ctrl-t 找到文件,继续输入目的地址即可。

如果想要更简单 fzf GitHub wiki 中展示了非常多的 Bash Shell 的配置 1,比如可以定义命令 fe

fe()  {  local files
  IFS=$'\n' files=($(fzf-tmux --query="$1"  --multi --select-1  --exit-0))  [[  -n "$files"  ]]  && ${EDITOR:-vim}  "${files[@]}"  }
1
2

那么在 shell 中直接输入 fe 然后回车会自动出现当前目录的 fzf,选择文件之后回车即可用默认 $EDITOR 打开文件。

多选

假如在 fzf 选择窗口中想要选择多个文件,那么可以使用 tab 来进行多选,使用 Ctrl-n, Ctrl-p 上下切换的时候,可以使用 Tab 来选中期望的文件进行多选操作。

比如移动,删除,或者编辑多个文件时可以使用。

更改路径

在 fzf 之前最原始的方法就是 cd 然后输入一个词,不断的按 Tab 直到完整的输入 Path,回车。但假如 path 比较长,那么可能需要费一些时间找到真正想要去的目录,而如果用 fzf 配置

fd()  {  local dir
  dir=$(find ${1:-.}  -path '*/\.*'  -prune \ -o -type d -print  2>  /dev/null  | fzf +m)  && cd "$dir"  }
1
2

在终端输入 fd 然后搜索一下目录回车就能直接到该目录下,效率提升 x 倍。

Kill Process

再比如说 fkill 用来 kill process

# fkill - kill process fkill()  {  local pid
  pid=$(ps -ef | sed 1d  | fzf -m | awk '{print $2}')  if  [  "x$pid"  !=  "x"  ]  then echo $pid | xargs kill -${1:-9}  fi  }
1
2

Tmux

再比如创建 Tmux session 一般都是 tmux new -s new-session 创建,如果使用 tmuxinator 则可能 mux name 比较快,但是如果在 fzf 这里只需要 tm new-session

# tm - create new tmux session, or switch to existing one. Works from within tmux too. (@bag-man)  # `tm` will allow you to select your tmux session via fzf.  # `tm irc` will attach to the irc session (if it exists), else it will create it. tm()  {  [[  -n "$TMUX"  ]]  && change="switch-client"  || change="attach-session"  if  [ $1 ];  then tmux $change -t "$1"  2>/dev/null  ||  (tmux new-session -d -s $1 && tmux $change -t "$1");  return  fi session=$(tmux list-sessions -F "#{session_name}"  2>/dev/null  | fzf --exit-0)  && tmux $change -t "$session"  || echo "No sessions found."  }
1

如果 session 不存在则会自动创建,使用 fs 可以快速选择目前可用的 session.

# fs [FUZZY PATTERN] - Select selected tmux session  #   - Bypass fuzzy finder if there's only one match (--select-1)  #   - Exit if there's no match (--exit-0) fs()  {  local session
  session=$(tmux list-sessions -F "#{session_name}"  | \
    fzf --query="$1"  --select-1  --exit-0)  && tmux switch-client -t "$session"  }
1
2
3

Alt-c

命令行中按下 Alt-c,会列出当前文件夹下的目录,选择后会直接进入该文件夹。

搜索语法

在上面一系列的基础操作后,对 fzf 应该有了一定的了解,那么知道 fzf 的搜索语法其实非常强大,在熟悉正则的基础上,用 fzf 搜索语法可以实现很多的组合,比如使用 ! 来表示不包含,比如 !word 不包含 word 的结果。

比如:

  • ^music 以 music 开头
  • mp3$ 以 mp3 结尾
  • 'word 严格匹配
  • !word 不包含 word
  • !.mp3$ 不以 .mp3 结尾

等等,可以在官方网站上看到。

扩展阅读

一些比较高效的搜索工具

  • find 目录搜索
  • fd 目录搜索
  • grep 文本内容搜索
  • ag 文本内容搜索
  • ripgrep 文本内容搜索

reference

  1. https://github.com/junegunn/fzf/wiki/examples